package com.leectrl.adapter;

import android.content.SharedPreferences;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hdl.school.application.MyApplication;
import com.hdl.school.bean.LastTCPMsg;
import com.hdl.school.bean.SerialMessage;
import com.hdl.school.utils.USBSerialManager;
import com.leectrl.utils.Bus;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;


public class DockingTCPServerHandler extends ChannelInboundHandlerAdapter {
    private CopyOnWriteArrayList<ChannelHandlerContext> mChannelHandlerContextList;
    private CopyOnWriteArrayList<String> ipList;
    private LastTCPMsg lastTCPMsg;
    private SharedPreferences sharedPreferences=MyApplication.myApplication.getSharedPreferences("school_iot", 0);


    public DockingTCPServerHandler(CopyOnWriteArrayList<ChannelHandlerContext> channelHandlerContexts, CopyOnWriteArrayList<String> ips) {
        ipList = ips;
        mChannelHandlerContextList = channelHandlerContexts;
        Bus.getInstance().on("publish_feedback_msg", new Bus.MessageEvent() {
            @Override
            public void onEvent(String key, Object... message) {
                JSONObject obj = (JSONObject) message[0];
                sendMessageToAllDevice(JSON.toJSONString(obj),true);
            }
        });
        Bus.getInstance().on("scene_event", new Bus.MessageEvent() {
            @Override
            public void onEvent(String key, Object... message) {
                String event = (String) message[0];
                JSONObject json = new JSONObject();
                json.put("type", "scene_event");
                json.put("event", event);
                sendMessageToAllDevice(JSON.toJSONString(json));
            }
        });
        //liuyong 下课联动关电脑
        Bus.getInstance().on("scene_event_liuyong", new Bus.MessageEvent() {
            @Override
            public void onEvent(String key, Object... message) {
                String event = (String) message[0];
                JSONObject json = new JSONObject();
                json.put("type", "scene_event");
                json.put("event", event);
                sendMessageToAllDevice(JSON.toJSONString(json));
            }
        });
        Bus.getInstance().on("screen_share", new Bus.MessageEvent() {
            @Override
            public void onEvent(String key, Object... message) {
                JSONObject jsonObject = JSON.parseObject((String) message[0]);
                JSONObject obj = new JSONObject();
                obj.put("type", "share_ip_ask");
                obj.put("share_info", jsonObject);
                sendMessageToAllDevice(JSON.toJSONString(obj));
            }
        });
        Bus.getInstance().on("tcp_serial", new Bus.MessageEvent() {
            @Override
            public void onEvent(String key, Object... message) {
                String code = (String) message[0];
                if(code!=null&&code.length()>=10){
                    JSONObject obj = new JSONObject();
                    obj.put("type", "tcp_serial");
                    obj.put("code", code);
                    sendMessageToAllDevice(JSON.toJSONString(obj),true);
                }
            }
        });


        Bus.getInstance().on("alive", new Bus.MessageEvent() {
            @Override
            public void onEvent(String key, Object... message) {
                sendMessageToAllDevice((String) message[0],true);
            }
        });
    }

    //收到数据时调用
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            ByteBuf in = (ByteBuf) msg;
            int readableBytes = in.readableBytes();
            byte[] bytes = new byte[readableBytes];
            in.getBytes(in.readerIndex(), bytes);
            String msgStr = new String(bytes);


            String[] arr = msgStr.split("\\}\\{");
            for (int k = 0; k < arr.length; k++) {
                String myMsg = arr[k];
                if (arr.length > 1) {
                    if (k == 0) {
                        myMsg = myMsg + "}";
                    } else if(k == arr.length-1){
                        myMsg = "{" + myMsg;
                    }else{
                        myMsg = "{" + myMsg+"}";
                    }
                }
                try {

                    JSONObject jsonObject = JSON.parseObject(myMsg);
                    if (!jsonObject.containsKey("type")) {
                        return;
                    }
                    if (lastTCPMsg != null && lastTCPMsg.getMsg() != null && lastTCPMsg.getMsg().equals(myMsg) && System.currentTimeMillis()-lastTCPMsg.getRevTime()<=2000) {
                        continue;
                    }
                    Log.e("tcp", myMsg);
                    lastTCPMsg = new LastTCPMsg();
                    lastTCPMsg.setMsg(myMsg);
                    lastTCPMsg.setRevTime(System.currentTimeMillis());
                    String type = jsonObject.getString("type");
                    JSONObject jsonObject1 = new JSONObject();
                    jsonObject1.put("type", type);
                    if ("auth".equals(type)) {
                        if ("DTZ!BK5h1E".equals(jsonObject.getString("code"))) {
                            jsonObject1.put("code", 0);
                            jsonObject1.put("msg", "Authentication success");
                            String deviceid = sharedPreferences.getString("DEVICEID", null);
                            if (deviceid == null) {
                                deviceid = UUID.randomUUID().toString().replaceAll("-", "");
                                sharedPreferences.edit().putString("DEVICEID", deviceid).commit();
                            }
                            jsonObject1.put("data", deviceid);
                            mChannelHandlerContextList.add(ctx);
                        } else {
                            jsonObject1.put("code", -1);
                            jsonObject1.put("msg", "Authentication error");
                        }

                    } else if ("ctrl".equals(type)) {
                        if (mChannelHandlerContextList.contains(ctx)) {
                            String action = jsonObject.getString("action");
                            Bus.getInstance().emit("exec_action", action, jsonObject.getJSONObject("params"), jsonObject.getString("protocol"), 3);
                            jsonObject1.put("code", 0);
                            jsonObject1.put("msg", "Send action success.");
                            if ("in_class".equals(action)) {
                                Bus.getInstance().emit("scene_event", "on_class");
                            } else if ("over_class".equals(action)) {
                                Bus.getInstance().emit("scene_event", "over_class");
                            }
                        } else {
                            jsonObject1.put("code", -2);
                            jsonObject1.put("msg", "unauthorized");
                        }
                    } else if ("status_feedback".equals(type)) {
                        JSONObject statusFeedbackObj = new JSONObject();
                        statusFeedbackObj.put("action", "status_feedback");
                        statusFeedbackObj.put("status", jsonObject.getJSONObject("data"));
                        Bus.getInstance().emit("publish_feedback_msg", statusFeedbackObj);
                    } else if ("screen_group".equals(type)) {
                        if (mChannelHandlerContextList.contains(ctx)) {
                            //问询目标屏幕的ip
                            JSONObject obj = new JSONObject();
                            obj.put("type", "share_ip_ask");
                            obj.put("share_info", jsonObject.getJSONObject("info"));
                            sendMessageToAllDevice(JSON.toJSONString(obj));
                        }
                    } else if ("screen_share".equals(type)) {
                        if (mChannelHandlerContextList.contains(ctx)) {
                            JSONObject obj = new JSONObject();
                            obj.put("type", "req_screen_share");
                            String clientInfo = String.valueOf(ctx.channel().remoteAddress());
                            String clientIP = clientInfo.substring(1, clientInfo.indexOf(":"));
                            obj.put("source_ip", clientIP);
                            obj.put("share_info", jsonObject.getJSONObject("info"));
                            sendMessageToOtherDevice(JSON.toJSONString(obj), clientIP);
                        }
                    } else if ("serial".equals(type)) {
                        //发送多条串口指令
                        if (mChannelHandlerContextList.contains(ctx)) {
                            JSONArray codes = jsonObject.getJSONArray("codes");
                            for (int i = 0; i < codes.size(); i++) {
                                JSONObject codeItem = codes.getJSONObject(i);
                                if (codeItem.containsKey("delay")) {
                                    USBSerialManager.getInstence().sendCtrlSerialCode(codeItem.containsKey("portType") ? codeItem.getString("portType") : null, codeItem.getString("code"), System.currentTimeMillis() + codeItem.getLongValue("delay"));
                                } else {
                                    USBSerialManager.getInstence().sendCtrlSerialCode(codeItem.containsKey("portType") ? codeItem.getString("portType") : null, codeItem.getString("code"), System.currentTimeMillis());
                                }
                            }

                        }
                    }else if ("switch_airctrl_status".equals(type)) {
                        //发送多条串口指令
                        if (mChannelHandlerContextList.contains(ctx)) {
                            USBSerialManager.getInstence().setAirctrlStatusEnable(jsonObject.getBoolean("enable"));
                        }
                    } else if ("tcp_serial".equals(type)) {
                        USBSerialManager.getInstence().sendLogMessage(new SerialMessage("TCP",jsonObject.getString("code"),"RX"));
                        USBSerialManager.getInstence().doCustomAction(jsonObject.getString("code"), null, "controlpanel");
                    } else if ("readConfig".equals(type)) {
                        if (mChannelHandlerContextList.contains(ctx)) {
                            String key = jsonObject.getString("key");
                            if (key == null) {
                                return;
                            }
                            String value = sharedPreferences.getString("setting_" + key, null);
                            if (value == null) {
                                return;
                            }
                            sharedPreferences.edit().remove("setting_" + key).commit();
                            jsonObject1.put("key", key);
                            jsonObject1.put("data", value);
                        }
                    }
                    byte[] respBytes = JSON.toJSONString(jsonObject1).getBytes();
                    ByteBuf buff = Unpooled.buffer();
                    // 对接需要16进制
                    buff.writeBytes(respBytes);
                    ctx.writeAndFlush(buff);
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e("DockingTCPServerHandler", ctx.channel().remoteAddress().toString() + "==>" + myMsg);
                }

            }


        } finally {

        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
        ctx.flush();
    }

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 当出现异常就关闭连接
        cause.printStackTrace();
        ipList.add(String.valueOf(ctx.channel().remoteAddress()));
        if(mChannelHandlerContextList.contains(ctx)){
            mChannelHandlerContextList.remove(ctx);
        }
        ctx.close();
    }

    /*
     * 建立连接时，返回消息
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        String clientInfo = String.valueOf(ctx.channel().remoteAddress());
        String clientIP = clientInfo.substring(1, clientInfo.indexOf(":"));
        if (ipList.indexOf(clientIP) >= 0) {
            //移除相同ip的连接
            List<ChannelHandlerContext> removeChannelHandlerContextList = new ArrayList<>();
            for (ChannelHandlerContext channelHandlerContext : mChannelHandlerContextList) {
                String mClientInfo = String.valueOf(channelHandlerContext.channel().remoteAddress());
                String mClientIP = mClientInfo.substring(1, mClientInfo.indexOf(":"));
                if (clientIP.equals(mClientIP)) {
                    removeChannelHandlerContextList.add(channelHandlerContext);
                }
            }
            mChannelHandlerContextList.removeAll(removeChannelHandlerContextList);
        } else {
            ipList.add(clientIP);
        }

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        String mClientInfo = String.valueOf(ctx.channel().remoteAddress());
        String mClientIP = mClientInfo.substring(1, mClientInfo.indexOf(":"));
        ipList.remove(mClientIP);
        mChannelHandlerContextList.remove(ctx);

    }

    private void sendUDPSerial(String code) {
        String broadMac=sharedPreferences.getString("c_setting_broadMac",null);
        if (broadMac == null) {
            return;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("action", "tcp_serial");
        jsonObject.put("target", broadMac);
        JSONArray codes = new JSONArray();
        JSONObject codeObj = new JSONObject();
        codeObj.put("code", code);
        codeObj.put("delay", 0);
        codes.add(codeObj);
        jsonObject.put("codes", codes);
        byte[] command = JSON.toJSONString(jsonObject).getBytes(StandardCharsets.UTF_8);
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            NetworkInterface networkInterface;
            Enumeration<InetAddress> inetAddresses;
            InetAddress inetAddress;
            while (networkInterfaces.hasMoreElements()) {
                networkInterface = networkInterfaces.nextElement();
                inetAddresses = networkInterface.getInetAddresses();
                while (inetAddresses.hasMoreElements()) {
                    inetAddress = inetAddresses.nextElement();
                    if (inetAddress != null && inetAddress instanceof Inet4Address) { // IPV4
                        InetSocketAddress inetAddr = new InetSocketAddress(inetAddress, 0);
                        //2.获取广播socket
                        DatagramSocket broadcastSocket = new DatagramSocket(inetAddr);
                        broadcastSocket.setBroadcast(true);
                        DatagramPacket packet = new DatagramPacket(command, command.length, InetAddress.getByName("255.255.255.255"), 12357);
                        //4.发送数据
                        broadcastSocket.send(packet);
                        //5.关闭socket
                        broadcastSocket.close();
                    }
                }
            }
        } catch (UnknownHostException e) {
            //Ip地址错误时候抛出的异常
            e.printStackTrace();
        } catch (IOException e) {
            //获取socket失败时候抛出的异常
            e.printStackTrace();
        }
    }

    private void sendMessageToAllDevice(String jsonStr) {
        sendMessageToAllDevice(jsonStr,false);
    }

    private void sendMessageToAllDevice(String jsonStr,boolean toBroad) {
        byte[] respBytes = jsonStr.getBytes();
        if (mChannelHandlerContextList.size() > 0) {
            for (ChannelHandlerContext channelHandlerContext : mChannelHandlerContextList) {
                try{
                    // netty需要用ByteBuf传输
                    ByteBuf buff = Unpooled.buffer();
                    // 对接需要16进制
                    buff.writeBytes(respBytes);
                    channelHandlerContext.writeAndFlush(buff);
                }catch (Exception e){
                    if(toBroad){
                        sendUDPSerial(jsonStr);
                    }
                }
            }
        }else{
            if(toBroad){
                sendUDPSerial(jsonStr);
            }
        }
    }

    private void sendMessageToOtherDevice(String jsonStr, String mIp) {
        byte[] respBytes = jsonStr.getBytes();
        if (mChannelHandlerContextList.size() > 0) {
            for (ChannelHandlerContext channelHandlerContext : mChannelHandlerContextList) {
                String clientInfo = String.valueOf(channelHandlerContext.channel().remoteAddress());
                String clientIP = clientInfo.substring(1, clientInfo.indexOf(":"));
                if (mIp.equals(clientIP)) {
                    continue;
                }
                // netty需要用ByteBuf传输
                ByteBuf buff = Unpooled.buffer();
                // 对接需要16进制
                buff.writeBytes(respBytes);
                channelHandlerContext.writeAndFlush(buff);
            }

        }
    }

}
